package ua.com.abakumov.android.prostopleer.engines

import scala.Predef._
import scala.StringBuilder

import java.net.{URLEncoder, URISyntaxException, URI}
import java.io._
import java.util
import java.util.{List => JList}
import java.nio.charset.Charset
import java.util.regex.{Matcher, Pattern}

import android.util.Log

import org.apache.http.HttpStatus
import org.apache.http.impl.client.DefaultHttpClient
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.utils.URIUtils
import org.jsoup.Jsoup

import ua.com.abakumov.android.prostopleer.tasks.DownloadTask
import ua.com.abakumov.android.prostopleer.util.Composition
import ua.com.abakumov.android.prostopleer.util.Functions._


/**
 * ProstoPlayerEngine

 * @author alexander-abakumov
 *         Date: 25.10.12
 */
class ProstoPlayerEngine extends Engine {

  // Init prostopleer URL
  protocol = "http"
  host = "prostopleer.com"
  port = "80"
  path = "/search"
  downloadPath = "/site_api/files/get_url"
  query = "q="
  downloadQuery = "action=download&id="
  fragment = null

  type Compositions = JList[Composition]

  override def mine(request: String): String = {
    var responseString: String = null

    try {
      val uri: URI = createURI(request)

      Log.d("Net:", uri.toString)

      val response = new DefaultHttpClient().execute(new HttpGet(uri))
      val statusLine = response.getStatusLine

      statusLine.getStatusCode match {
        case HttpStatus.SC_OK => {
          val out: ByteArrayOutputStream = new ByteArrayOutputStream
          response.getEntity.writeTo(out)
          out.close()

          responseString = out.toString
        }
        case _ : Int => {
          response.getEntity.getContent.close()
          throw new IOException(statusLine.getReasonPhrase)
        }
      }

    } catch {
      case e: Exception => e.printStackTrace()
    }

    responseString
  }

  override def parse(rawResult: String): Compositions = {

    /**
     * Extract tracks html to help html parser (make it faster)
     *
     * @param html raw html
     * @return clean html
     */
    def extractTracks(html: String): String = {
      val pattern: Pattern = Pattern.compile("<li duration(?:\"[^\"]*\"['\"]*|'[^']*'['\"]*|[^'\">])+>")
      val matcher: Matcher = pattern.matcher(html)
      val sb: StringBuilder = new StringBuilder
      while (matcher.find) {
        val group: String = matcher.group
        sb.append(group)
      }
      sb.toString()
    }

    val compositions = new util.ArrayList[Composition]

    val html = extractTracks(rawResult)
    val doc = Jsoup.parse(html)
    val lis = doc.select("li")

    import scala.collection.JavaConversions._
    for (row <- lis) {
      val link: String = row.attr("link")
      val singer: String = row.attr("singer")
      val song: String = row.attr("song")
      val size: String = row.attr("size")
      compositions.add(Composition(link, singer, song, size))
    }

    compositions
  }

  override def download(composition: Composition) {
    startedDownloadingListener("")

    val downloadTask = new DownloadTask(
      protocol,
      host,
      downloadPath,
      downloadQuery,
      (fName: String) => {
        compositionSavedListener(fName)

        Log.i("Saved:", fName)
      })

    downloadTask.execute(composition)
  }

  @throws(classOf[URISyntaxException])
  private def createURI(requestString: String): URI = {
      // TODO: use port
      val encodedString = URLEncoder.encode(requestString, Charset.defaultCharset().name())
      URIUtils.createURI(protocol, host, -1, path, query + encodedString, null)
  }
}